package com.codeark.appengine;

import static com.google.appengine.api.urlfetch.FetchOptions.Builder.disallowTruncate;

import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;

import com.google.appengine.api.urlfetch.FetchOptions;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.common.base.Joiner;


/**
 * 
 * @author Yaniv Kessler (yaniv at codeark dot com)
 * 
 */
public abstract class AbstractUrlFetchServiceFacade<T> implements UrlFetchServiceFacade<T> {

	private final URLFetchService web;
	protected FetchOptions options;

	public AbstractUrlFetchServiceFacade(URLFetchService web) {
		this.web = web;
		this.options = disallowTruncate().followRedirects().setDeadline(5d);
	}

	public T get(URL url) throws IOException {
		return getImpl(url);
	}

	@Override
	public T get(URL url, HTTPHeader... headers) throws IOException {
		return getImpl(url, headers);
	}

	protected T getImpl(URL url, HTTPHeader... headers) throws IOException {
		HTTPRequest request = new HTTPRequest(url, HTTPMethod.GET, options);
		for (HTTPHeader header : headers)
			request.addHeader(header);

		HTTPResponse response = web.fetch(request);

		return convertResponse(response);
	}

	@Override
	public T post(URL url, Map<String, String> data) throws IOException {
		return postImpl(url, data);
	}

	@Override
	public T post(URL url, Map<String, String> data, HTTPHeader... headers) throws IOException {
		return postImpl(url, data, headers);
	}

	protected T postImpl(URL url, Map<String, String> data, HTTPHeader... headers) throws IOException {
		HTTPRequest request = new HTTPRequest(url, HTTPMethod.POST, options);

		for (HTTPHeader header : headers)
			request.addHeader(header);

		String rawPayload = Joiner.on("&").withKeyValueSeparator("=").join(data);
		request.setPayload(rawPayload.getBytes(Charset.forName("utf8")));

		HTTPResponse response = web.fetch(request);

		return convertResponse(response);
	}

	protected abstract T convertResponse(HTTPResponse response) throws IOException;
}
